package com.ophiux.service.order.api.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

/**
 * 流控规则
 * 1.如何使用: https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
 */
@RestController
public class SentinelServiceImpl {
	//限流规则名称
	private static final String GETORDER_KEY = "getOrder";
	

	//1.手动创建流量控制规则
	@RequestMapping("/initFlowQpsRule")
	public String initFlowQpsRule() {
		List<FlowRule> rules = new ArrayList<FlowRule>();
		FlowRule rule1 = new FlowRule();
		rule1.setResource(GETORDER_KEY);//资源名，即规则的作用对象
		// QPS 限流阈值     每秒次数
		rule1.setCount(1);
		// QPS限流
		rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);//限流阈值类型，QPS 模式（1）或并发线程数模式（0）
		rule1.setLimitApp("default");//流控针对的调用来源
		rules.add(rule1);
		FlowRuleManager.loadRules(rules);
		return "....限流配置初始化成功..";
	}

	@RequestMapping("/getOrder")
	public String getOrders() {
		Entry entry = null;
		try {
			entry = SphU.entry(GETORDER_KEY);
			// 执行我们服务需要保护的业务逻辑
			
			return "getOrder接口";
		} catch (Exception e) {
			e.printStackTrace();
			return "该服务接口已经达到上线!";
		} finally {
			// SphU.entry(xxx) 需要与 entry.exit() 成对出现,否则会导致调用链记录异常
			if (entry != null) {
				entry.exit();
			}
		}
	}
	
	//2.spring 启动加载
	
	/**
     	3.注解形式配置管理Api限流
	  	@SentinelResource  
		fallback 服务的降级执行的方法
		blockHandler 限流/熔断出现异常执行的方法
	    value参数：流量规则资源名称、
	 */
	@SentinelResource(value = GETORDER_KEY, blockHandler = "getOrderQpsException")
	@RequestMapping("/getOrder2")
	public String getOrders2() {
		return "getOrders2接口，注解形式限流";
	}
	
	/**
	 * 被限流后返回的提示
	 * @param e
	 * @return
	 */
	public String getOrderQpsException(BlockException e) {
	    e.printStackTrace();
	    return "该接口已经被限流啦!";
	}
	
	/**
	 * 连接控制台限流规则
	 * 没有使用@@SentinelResource，默认的资源名称为接口路径    /getOrder3   如果使用注解，还是写成getOrder3
	 * @return
	 */
	@RequestMapping("/getOrder3")
	@SentinelResource(value = "getOrder3",blockHandler = "getOrderQpsException")
	public String getOrder3() {
		return "getOrder3接口，连接控制台限流规则";
	}
	
	
	@SentinelResource(value = "getOrderThrad", blockHandler = "getOrderQpsException")
	@RequestMapping("/getOrderThrad")
	public String getOrderThrad() {
	    System.out.println(Thread.currentThread().getName());
	    try {
	        Thread.sleep(500);
	    } catch (Exception e) {

	    }
	    return "getOrderThrad";
	}
	
	
	
	@RequestMapping("/getOrder4")
	@SentinelResource(value = "getOrder4", blockHandler = "getOrderQpsException")
	public String getOrder4() {
		return "getOrder4接口，sentinel整合nacos持久化，连接控制台限流规则";
	}
	
	
}
